package com.castile.functional.hiorder;

import java.util.*;
import java.util.function.*;

/**
 * @description:
 * @author: Castile
 * @create: 2024-04-17 20:15
 * @Version 1.0
 **/
public class SimpleStream<T> {
    private Collection<T> collection;

    public static void main(String[] args) {
//        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
//        SimpleStream.of(list)
//                .filter(x -> (x & 1) == 1)
//                .map(x -> x * x)
//                .forEach(System.out::println);


        // 取出最大值
//        System.out.println(SimpleStream.of(list).reduce(Integer.MAX_VALUE, Integer::min));
//
//        // 取出最小值
//        System.out.println(SimpleStream.of(list).reduce(Integer.MIN_VALUE, Integer::max));
//
//        // 求和
//        System.out.println(SimpleStream.of(list).reduce(0, Integer::sum));


        List<Integer> list = Arrays.asList(1, 2, 1, 1, 5, 6, 1, 8);

        HashSet<Integer> colletc = SimpleStream.of(list)
                .collect(HashSet::new, HashSet::add);

        System.out.println(colletc);

    }



    public <C> C collect(Supplier<C> supplier, BiConsumer<C, T> consumer) {
        C c = supplier.get();
        for (T t : collection) {
            consumer.accept(c, t);
        }
        return c;
    }

    public T reduce(T init, BinaryOperator<T> operator) {
        T p = init;
        for (T t : collection) {
            p = operator.apply(p, t);
        }
        return p;
    }

    public void forEach(Consumer<T> consumer) {
        for (T t : collection) {
            consumer.accept(t);
        }
    }

    public SimpleStream<T> filter(Predicate<T> predicate) {
        ArrayList<T> list = new ArrayList<>();

        for (T t : collection) {
            if (predicate.test(t)) {
                list.add(t);
            }
        }

        return new SimpleStream<>(list);
    }


    public <U> SimpleStream<U> map(Function<T, U> function) {
        ArrayList<U> list = new ArrayList<>();

        for (T t : collection) {
            list.add(function.apply(t));
        }

        return new SimpleStream<>(list);
    }

    public static <T> SimpleStream<T> of(Collection<T> collection) {
        return new SimpleStream<>(collection);
    }

    private SimpleStream(Collection<T> collection) {
        this.collection = collection;
    }
}
